﻿using System;
using System.Collections.Generic;
using Fujitsu.JiraAnalysis.DAL;
using Fujitsu.JiraAnalysis.TrackingSystemAdapter;
using Fujitsu.JiraAnalysis.ReplicationService.SynchronizeExceptions;
using Fujitsu.JiraAnalysis.JiraRPC;
using Fujitsu.JiraAnalysis.Common;

namespace Fujitsu.JiraAnalysis.ReplicationService.Synchronize
{
    public class ProjectSync
    {
        public ProjectStorage projectStorage = new ProjectStorage();
        public UserStorage userStorage = new UserStorage();

        public SyncBase<RemoteIssueType, IssueTypeMapping> issuesTypesSync = new IssuesTypesSync();
        public SyncBase<RemotePriority, PriorityMapping> issuePrioritySync = new IssuePrioritySync();
        public SyncBase<RemoteStatus, StatusMapping> issueStatusSync = new IssueStatusSync();
        public SyncBase<RemoteResolution, ResolutionMapping> issueResolutionSync = new IssueResolutionSync();

        public static List<int> CurrentlyReplicatingProjects = new List<int>();

        public IEventLog eventLog = new EventLogWrapper();
        public bool IsReplicationRunning { get; set; }

        public void ReplicateProject(Project project, IAdapterCreator adapterCreator)
        {
            if (CurrentlyReplicatingProjects.Contains(project.ID))
            {
                EventLogger.CreateInstance(eventLog).LogWriteWarning(string.Format("'{0}' is already being replicated.", project.Name));
                return;
            }
            CurrentlyReplicatingProjects.Add(project.ID);
            EventLogger.CreateInstance(eventLog).LogWrite(string.Format("Repplication of project '{0}' service started at {1}", project.Name, DateTime.Now.ToString("G")));
            
            var adapter = adapterCreator.CreateJiraSoapServiceAdapter(project.JiraLogin, project.JiraPassword, project.JiraUrl);
            try
            {
                var jiraProject = adapter.GetProjectByKey(project.ProjectKey);

                if (project.User != null && project.User.Login != jiraProject.lead || project.User == null)
                {
                    var jiraUser = adapter.GetUser(jiraProject.lead);
                    var userId = userStorage.AddOrUpdateUser(jiraUser.name, jiraUser.name, jiraUser.fullname);
                    projectStorage.UpdateProjectLead(project.ID, userId);
                    EventLogger.CreateInstance(eventLog).LogWrite(string.Format("User '{0}' is now leading '{1}' project.", jiraUser.name, project.Name));
                }
            }
            catch (TrackSystemCommunicationException ex)
            {
                EventLogger.CreateInstance(eventLog).LogWriteError(ex.Message);
            }

            //mapping sync
            try
            {
                issuesTypesSync.StartSync(adapter, project);
                issuePrioritySync.StartSync(adapter, project);
                issueStatusSync.StartSync(adapter, project);
                issueResolutionSync.StartSync(adapter, project);
            }
            catch (SyncException ex)
            {
                projectStorage.SetNeedCheckProject(project);
                EventLogger.CreateInstance(eventLog).LogWriteError(ex.Message);
                return;
            }
            catch (Exception ex)
            {
                //EventLogger.CreateInstance(eventLog).LogWriteError(ex.Message);
                EventLogger.CreateInstance(eventLog).LogWriteError(string.Format("{0}\n\r{1}", ex.Message, ex.StackTrace));
            }

            //Versions, Issues, Worklogs - replication
            var projectVersionSync = new ProjectVersionUpdate(adapter, project.ID, project.ProjectKey, project.Name);
            var issueSync = new ProjectIssueUpdate(adapter, project.ID, project.ProjectKey, project.Name);
            try
            {
                projectVersionSync.Update();
                issueSync.Update();
            }
            catch (Exception ex)
            {
                //EventLogger.CreateInstance(eventLog).LogWriteError(ex.Message);
                EventLogger.CreateInstance(eventLog).LogWriteError(string.Format("{0}\n\r{1}",ex.Message,ex.StackTrace));
            }
            EventLogger.CreateInstance(eventLog).LogWrite(string.Format("Repplication of project '{0}' service stopped at {1}", project.Name, DateTime.Now.ToString("G")));
            CurrentlyReplicatingProjects.Remove(project.ID);
        }

        public void StartReplication(IAdapterCreator adapterCreator)
        {
            IsReplicationRunning = true;
            EventLogger.CreateInstance(eventLog).LogWrite(string.Concat("Repplication service started at ", DateTime.Now.ToString("G")));

            foreach (var project in projectStorage.GetProjectsToSynchronize())
            {
                ReplicateProject(project, adapterCreator);
            }

            EventLogger.CreateInstance(eventLog).LogWrite(string.Concat("Repplication service stopped at ", DateTime.Now.ToString("G")));
            IsReplicationRunning = false;
        }
    }
}
